
#import "WW3DAttributeState.h"

#import "usefulWW3DFunctions.h"

@implementation WW3DAttributeState

+ initialize { return [WW3DAttributeState setVersion:1], self; }

- init
{
  [super init];
  N3D_CopyMatrix(N3DIdentityMatrix, ctm);
  boundingBox[0] = 0.0;
  boundingBox[1] = 0.0;
  boundingBox[2] = 0.0;
  boundingBox[3] = 0.0;
  boundingBox[4] = 0.0;
  boundingBox[5] = 0.0;
  hasBoundingBox = NO;

  return self;
}

- (BOOL)hasBoundingBox { return hasBoundingBox; }
- setHasBoundingBox:(BOOL)flag { hasBoundingBox = flag;  return self; }

- growBoundingBox:(RtBound *)newBoundingBox
{
  if (hasBoundingBox)
  {  // we need to "grow" our boundingBox w re: to this new one
     // the idea here is that our boundingBox is current to our ctm,
     // but this incoming bound needs to be transformed by the ctm.  
     // Once it's been transformed into the same space, we recompare 
     // bounding boxes, and update ours based on the mins and maxes
     // of those two bounds
     RtBound  tmpBoundingBox;


     WW3DDetermineBoundGivenBoundAndCTM(&tmpBoundingBox, newBoundingBox,  ctm);
     //// X
     if (tmpBoundingBox[0] < boundingBox[0])
     {  boundingBox[0] = tmpBoundingBox[0];
     }
     if (tmpBoundingBox[1] > boundingBox[1])
     {  boundingBox[1] = tmpBoundingBox[1];
     }
     //// Y
     if (tmpBoundingBox[2] < boundingBox[2])
     {  boundingBox[2] = tmpBoundingBox[2];
     }
     if (tmpBoundingBox[3] > boundingBox[3])
     {  boundingBox[3] = tmpBoundingBox[3];
     }
     //// Z
     if (tmpBoundingBox[4] < boundingBox[4])
     {  boundingBox[4] = tmpBoundingBox[4];
     }
     if (tmpBoundingBox[5] > boundingBox[5])
     {  boundingBox[5] = tmpBoundingBox[5];
     }
  }
  else // first time; set 
  {  N3D_CopyBound(*newBoundingBox, boundingBox);
     // now transform these points by the ctm
     WW3DDetermineBoundGivenBoundAndCTM(&boundingBox, &boundingBox,  ctm);
     hasBoundingBox = YES;
  }

  return self;
}

- (RtBound *)boundingBox {  return &boundingBox; }

- setTransformMatrix:(RtMatrix)newMatrix
{
  N3D_CopyMatrix(newMatrix, ctm);
  return self;
}

- getTransformMatrix:(RtMatrix)matrix
{
  N3D_CopyMatrix(ctm, matrix);
  return self;
}

- translate:(RtFloat)dx :(RtFloat)dy :(RtFloat)dz
{
  RtMatrix  tmp;


  N3D_CopyMatrix(N3DIdentityMatrix, tmp);
  tmp[3][0] = dx;
  tmp[3][1] = dy;
  tmp[3][2] = dz;

  N3DMultiplyMatrix(ctm, tmp, ctm);

  return self;
}


- read:(NXTypedStream*)stream 
{
    int version;
    [super read:stream];

    version = NXTypedStreamClassVersion(stream,"WW3DAttributeState");
    if (version == 0) NXReadTypes(stream, "i", &version), version=1;
    if (version == 1)
    {  NXReadArray(stream, "f", 4, ctm[0]);
       NXReadArray(stream, "f", 4, ctm[1]);
       NXReadArray(stream, "f", 4, ctm[2]);
       NXReadArray(stream, "f", 4, ctm[3]);
    } 

    return self;
}

- write:(NXTypedStream *)stream 
{
    [super write:stream];

    NXWriteArray(stream, "f", 4, ctm[0]);
    NXWriteArray(stream, "f", 4, ctm[1]);
    NXWriteArray(stream, "f", 4, ctm[2]);
    NXWriteArray(stream, "f", 4, ctm[3]);

    return self;
}

@end
